package ua.kharkov.khpi.tarasenko.bach.web.command.user;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import ua.kharkov.khpi.tarasenko.bach.core.Constant;
import ua.kharkov.khpi.tarasenko.bach.core.LocalizedResourceManager;
import ua.kharkov.khpi.tarasenko.bach.core.EShopException;
import ua.kharkov.khpi.tarasenko.bach.core.db.ConnectionManager;
import ua.kharkov.khpi.tarasenko.bach.core.db.DBUtils;
import ua.kharkov.khpi.tarasenko.bach.core.item.ItemBean;
import ua.kharkov.khpi.tarasenko.bach.core.order.OrderStatus;
import ua.kharkov.khpi.tarasenko.bach.core.user.ShoppingCart;
import ua.kharkov.khpi.tarasenko.bach.core.user.UserBean;
import ua.kharkov.khpi.tarasenko.bach.dao.core.DAOFactory;
import ua.kharkov.khpi.tarasenko.bach.dao.core.order.OrderItemDAO;
import ua.kharkov.khpi.tarasenko.bach.dao.core.order.OrderItemDTO;
import ua.kharkov.khpi.tarasenko.bach.dao.core.order.OrderUserDAO;
import ua.kharkov.khpi.tarasenko.bach.dao.core.order.OrderUserDTO;
import ua.kharkov.khpi.tarasenko.bach.web.command.Command;

/**
 * Command to place order.
 * 
 * @author oleksandr
 * 
 */
public class PlaceOrderCommand extends Command {
	private static final Logger log = Logger.getLogger(PlaceOrderCommand.class);

	@Override
	public String execute(HttpServletRequest request,
			HttpServletResponse response) throws EShopException {

		// Get UserBean from session
		HttpSession session = request.getSession();
		UserBean userBean = (UserBean) session
				.getAttribute(Constant.ATTRIBUTE_USER_BEAN);

		// Create object with general order's info
		OrderUserDTO orderUserDTO = new OrderUserDTO();
		orderUserDTO.setUserId(userBean.getUserId());
		orderUserDTO.setStatus(OrderStatus.ORDERED);
		orderUserDTO.setOrderDate(new Date());

		// Get shopping cart from userBean and extract from it items to order
		ShoppingCart cart = userBean.getShoppingCart();
		List<OrderItemDTO> itemsToOrder = extractOrderItems(cart);

		String forward = Constant.PAGE_PLACE_ORDER_RESULT;
		String errorMessage = null;
		boolean isOrderPlaced = false;
		Connection conn = null;
		try {
			conn = ConnectionManager.getConnection();

			// Place order
			OrderUserDAO orderUserDAO = DAOFactory.getDAOFactory(
					DAOFactory.DAO_TYPE.MYSQL).getOrderUserDAO(conn);
			int orderId = orderUserDAO.addOrder(orderUserDTO);

			request.setAttribute(Constant.ATTRIBUTE_ORDER_ID, orderId);
			if (log.isTraceEnabled()) {
				if (log.isTraceEnabled()) {
					log.trace("Set request attribute "
							+ Constant.ATTRIBUTE_ORDER_ID + "=" + orderId);
				}
			}

			// Now we have order's id, so we can set it to our orderItemDTO
			// objects
			for (OrderItemDTO orderItemDTO : itemsToOrder) {
				orderItemDTO.setOrderId(orderId);
			}

			// Placing items for already placed order
			OrderItemDAO orderItemDAO = DAOFactory.getDAOFactory(
					DAOFactory.DAO_TYPE.MYSQL).getOrderItemDAO(conn);

			// Create LocalizedResourceManager to get localized error messages
			LocalizedResourceManager LRManager = getLocalizedResourceManager(request);

			int totalAdded = 0;
			int rowsAdded = 0;
			for (OrderItemDTO orderItemDTO : itemsToOrder) {
				rowsAdded = orderItemDAO.addItemToOrder(orderItemDTO);

				// If item was not added - break loop
				if (rowsAdded != 1) {
					errorMessage = LRManager.getMessage("error_message.order_cant_place");
					log.warn("Can't place order (id="
							+ orderItemDTO.getOrderId()
							+ "): can't place item with id="
							+ orderItemDTO.getItemId());
					break;
				}
				totalAdded += rowsAdded;
			}

			if (totalAdded != itemsToOrder.size()) {

				// If not all rows were added - roll back the transaction.
				DBUtils.rollBackAndClose(conn);
			} else {

				// So now order is completely placed
				isOrderPlaced = true;
				request.setAttribute(Constant.ATTRIBUTE_IS_ORDER_PLACED,
						isOrderPlaced);
				if (log.isTraceEnabled()) {
					log.trace("Set request attribute "
							+ Constant.ATTRIBUTE_IS_ORDER_PLACED + "="
							+ isOrderPlaced);
				}

				DBUtils.commitAndClose(conn);
			}
		} catch (EShopException e) {
			DBUtils.rollBackAndClose(conn);
			throw e;
		} finally {
			if (conn != null) {
				DBUtils.close(conn);
			}
		}

		if (errorMessage != null) {
			forward = processError(request, errorMessage);
		}

		if (log.isDebugEnabled()) {
			log.debug("Forward to " + forward);
		}
		return forward;
	}

	/**
	 * Extracts items from cart to order. <br>
	 * IMPORTANT! Don't forget to set order's id for received items before
	 * adding them to data store.
	 * 
	 * @param cart
	 *            where items are stored.
	 * @return itemsToOrder
	 */
	private ArrayList<OrderItemDTO> extractOrderItems(ShoppingCart cart) {
		ArrayList<OrderItemDTO> itemsToOrder = new ArrayList<OrderItemDTO>();

		OrderItemDTO orderItemDTO = null;
		for (Map.Entry<ItemBean, Integer> entry : cart.getCart().entrySet()) {
			ItemBean iteamBean = entry.getKey();
			int quantity = entry.getValue();

			orderItemDTO = new OrderItemDTO();
			orderItemDTO.setItemId(iteamBean.getId());
			orderItemDTO.setItemQuantity(quantity);
			itemsToOrder.add(orderItemDTO);
		}

		return itemsToOrder;
	}
}